using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Threading;
using RandomSearch.Host;
using RandomSearch.PluginsCommon;
using RandomSearch.Common;

namespace RandomSearch.VM {
    internal class SearchServiceClient : IDisposable {
        private readonly Uri _address;
        private int _attemptsCount = 10;
        private bool _disposed;
        private ChannelFactory<ISearchServer> _pipeFactory;
        private ISearchServer _pipeProxy;

        public SearchServiceClient(Uri uri) {
            _address = uri;
        }

        #region IDisposable Members

        public void Dispose() {
            if (_disposed) return;
            try {
                if (null != _pipeFactory) {
                    if (CommunicationState.Faulted != _pipeFactory.State) {
                        if (CommunicationState.Closed != _pipeFactory.State)
                            _pipeFactory.Close();
                    }
                    else
                        _pipeFactory.Abort();
                }
            }catch(CommunicationException){}
            _disposed = true;
        }

        #endregion

        public void Init() {
            while (_attemptsCount-- >= 0) {
                try {
                    _pipeFactory = new ChannelFactory<ISearchServer>(new NetNamedPipeBinding("netPipeConfig"),
                                                                     new EndpointAddress(_address));

                    _pipeFactory.Open();
                    _pipeProxy = _pipeFactory.CreateChannel();
                    _pipeProxy.DoHeating();
                    return;
                }
                catch (EndpointNotFoundException) {
                    if (null != _pipeFactory)
                        _pipeFactory.Abort();
                    Thread.Sleep(TimeSpan.FromSeconds(0.5d));
                    continue;
                }
            }
            throw new EndpointNotFoundException("Cannot find search server with adress {0}".ƒ(_address));
        }

        public void CancelSearch() {
            _pipeProxy.CancelSearch();
        }

        public void StartSearch(SearchOptions o) {
            _pipeProxy.StartSearch(o);
        }

        public void RefreshPlugins() {
            _pipeProxy.RefreshPlugins();
        }

        public IEnumerable<FileInfo> GetReadyResults(ref bool completed) {
            ReadyResultsResponse res = _pipeProxy.GetReadyResults();
            if (null != res.Error) throw res.Error;
            completed = !res.InProgress;
            if (null != res.Results)
                return res.Results.Select(x => new FileInfo(x.File));
            return null;
        }

        public IEnumerable<SearchPluginData> GetPlugins() {
            return _pipeProxy.GetListOfPlugins();
        }
    }
}